package org.suze.springboot.elasticsearch.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.suze.springboot.elasticsearch.param.BaseSearchParam;
import org.suze.springboot.elasticsearch.service.ElasticSearchService;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static org.elasticsearch.client.RequestOptions.DEFAULT;

/**
 * @description: 抽象ElasticSearchService
 * @Date : 2020/5/14 上午11:33
 * @Author : 石冬冬-Seig Heil
 */
@Service
@Slf4j
public class ElasticSearchServiceImpl implements ElasticSearchService {

    @Autowired
    RestHighLevelClient client;

    @Override
    public boolean exists(String index) {
        boolean exists;
        try {
            GetIndexRequest getIndexRequest = new GetIndexRequest(index);
            getIndexRequest.humanReadable(true);
            exists = client.indices().exists(getIndexRequest, DEFAULT);
        } catch (IOException e) {
            log.error("[ElasticSearch]exists，index={}",index, e);
            throw new RuntimeException("[ElasticSearch]exists异常");
        }
        return exists;
    }

    @Override
    public boolean deleteIndex(String... indices) {
        boolean acknowledged;
        try {
            DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indices);
            AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest,DEFAULT);
            acknowledged = delete.isAcknowledged();
        } catch (IOException e) {
            log.error("[ElasticSearch]deleteIndex，indices={}", JSON.toJSONString(indices), e);
            throw new RuntimeException("[ElasticSearch]deleteIndex异常");
        }
        return acknowledged;
    }

    @Override
    public List<SearchHit> queries(BaseSearchParam param) {
        SearchRequest searchRequest = (SearchRequest)param.request();

        List<SearchHit> resultSearchHit = Lists.newArrayList();
        try {
            SearchResponse searchResponse = client.search(searchRequest, DEFAULT);
            //游标
            String scrollId = searchResponse.getScrollId();
            SearchHit[] searchHits = searchResponse.getHits().getHits();

            while (searchHits.length > 0) {
                resultSearchHit.addAll(Arrays.asList(searchHits));

                SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
                searchScrollRequest.scroll(param.createScroll());
                SearchResponse searchScrollResponse = client.scroll(searchScrollRequest, DEFAULT);
                scrollId = searchScrollResponse.getScrollId();
                searchHits = searchScrollResponse.getHits().getHits();

            }
            if(!StringUtils.isEmpty(scrollId)){
                //及时清除es快照，释放资源
                ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
                clearScrollRequest.addScrollId(scrollId);
                client.clearScroll(clearScrollRequest,DEFAULT);
            }
        } catch (Exception e) {
            log.error("[ElasticSearch]queries，param={}", JSON.toJSONString(searchRequest), e);
            throw new RuntimeException("[ElasticSearch]queries异常");
        }
        return resultSearchHit;
    }

    @Override
    public Map<String, Object> query(String index, String id) {
        GetRequest request = new GetRequest(index);
        try {
            request.id(id);
            return client.get(request,DEFAULT).getSourceAsMap();
        } catch (Exception e) {
            log.error("[ElasticSearch]query，index={},id={}", index, id, e);
            throw new RuntimeException("[ElasticSearch]query异常");
        }
    }
}
